package com.fla.puzzle.ui;

import java.util.Collections;
import java.util.List;

import junit.framework.Assert;

import com.danikula.aibolit.Aibolit;
import com.danikula.aibolit.annotation.InjectService;
import com.danikula.aibolit.annotation.InjectView;
import com.fla.puzzle.CompletedManager;
import com.fla.puzzle.CompletedManager.OnPackItemCompletedListener;
import com.fla.puzzle.PackManager;
import com.fla.puzzle.PuzzleApplication;
import com.fla.puzzle.R;
import com.fla.puzzle.pack.Pack;
import com.fla.puzzle.pack.PackItem;
import com.fla.puzzle.ui.game.GameModel;
import com.fla.puzzle.ui.support.CustomGallery;
import com.fla.puzzle.ui.support.ReflectedDisplayer;
import com.fla.puzzle.utils.Utils;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Shows 'Select Puzzle' screen
 */
public class PuzzleSelectorActivity extends BaseActivity {
    private static final String PACK_ID_KEY = PuzzleSelectorActivity.class.getName() + "PACK_ID_KEY";

    private static final int LEVEL_SELECTOR_ACTIVITY_REQUESR_CODE = 1;

    private PackManager packManager = PuzzleApplication.getInstance().getPackManager();

    @InjectService
    private CompletedManager completedManager;

    @InjectView(R.id.puzzleGallery)
    private CustomGallery puzzleGallery;

    private PuzzleAdapter puzzleAdapter;

    private OnPackItemCompletedHandler completedHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String packId = getIntent().getExtras().getString(PACK_ID_KEY);
        Assert.assertNotNull(packId);

        Aibolit.setInjectedContentView(this, R.layout.puzzle_selector_activity);

        Pack pack = packManager.getPackById(packId);

        puzzleAdapter = new PuzzleAdapter();
        puzzleGallery.setAdapter(puzzleAdapter);
        puzzleGallery.setOnItemClickListener(new ItemClickedHandler());
        puzzleAdapter.setPacks(pack.getPackItems());

        completedHandler = new OnPackItemCompletedHandler();
        completedManager.addOnPackItemCompletedListener(completedHandler);
    }

    @Override
    protected void onDestroy() {
        completedManager.removeOnPackItemCompletedListener(completedHandler);
        super.onDestroy();
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        if (puzzleAdapter.isChanged) {
            puzzleAdapter.notifyDataSetChanged();
        }
    }

    /**
     * Starts {@link PuzzleSelectorActivity} activity and passes the given pack id in extras
     * 
     * @param context Context the context of invoking component
     * @param packId String game package id
     */
    public static void start(Context context, String packId) {
        Intent intent = new Intent(context, PuzzleSelectorActivity.class);
        intent.putExtra(PACK_ID_KEY, packId);
        context.startActivity(intent);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case LEVEL_SELECTOR_ACTIVITY_REQUESR_CODE:
                if (resultCode == RESULT_OK) {
                    handleLevelSelected(data);
                }
                break;
            default:
                throw new IllegalArgumentException("Unsupported request code: " + requestCode);
        }
    }

    private void handleLevelSelected(Intent data) {
        Assert.assertTrue(data.hasExtra(LevelSelectorActivity.ROWS_COUNT_KEY));
        Assert.assertTrue(data.hasExtra(LevelSelectorActivity.COLS_COUNT_KEY));

        int rowsCount = data.getIntExtra(LevelSelectorActivity.ROWS_COUNT_KEY, 0);
        int colsCount = data.getIntExtra(LevelSelectorActivity.COLS_COUNT_KEY, 0);

        PackItem selectedItem = (PackItem) data.getSerializableExtra(LevelSelectorActivity.ITEM_KEY);

        GameActivity.start(this, new GameModel(rowsCount, colsCount, selectedItem), true);
    }

    private class PuzzleAdapter extends BaseAdapter {
        private List<PackItem> puzzles = Collections.EMPTY_LIST;
        private DisplayImageOptions options;
        private boolean isChanged = false;

        public PuzzleAdapter() {
            options = new DisplayImageOptions.Builder().cacheInMemory().displayer(new ReflectedDisplayer(2))
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2).build();
        }

        public void setPacks(List<PackItem> puzzles) {
            this.puzzles = puzzles;
            notifyDataSetChanged();
        }
        
        public void markAsChanged() {
            isChanged = true;
        }
        
        @Override
        public void notifyDataSetChanged() {
            isChanged = false;
            super.notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return puzzles.size();
        }

        @Override
        public PackItem getItem(int position) {
            return puzzles.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = convertView;
            if (view == null) {
                view = LayoutInflater.from(PuzzleSelectorActivity.this).inflate(R.layout.puzzle_gallery_item, null);
            }

            PackItem packItem = getItem(position);

            TextView name = (TextView) view.findViewById(R.id.name);
            ImageView image = (ImageView) view.findViewById(R.id.image);
            ImageView completedImage = (ImageView) view.findViewById(R.id.completedImage);

            name.setTypeface(PuzzleApplication.getInstance().getHeaderTypeface());
            name.setText(packItem.getName());
            completedImage.setVisibility(completedManager.isCompleted(packItem) ? View.VISIBLE : View.GONE);

            ImageLoader.getInstance().displayImage(Utils.toURI(packItem.getImageId()).toString(), image, options);

            return view;
        }
    }

    private class ItemClickedHandler implements OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            PackItem selectedItem = puzzleAdapter.getItem(position);
            LevelSelectorActivity.startForResult(PuzzleSelectorActivity.this, selectedItem, LEVEL_SELECTOR_ACTIVITY_REQUESR_CODE);
        }
    }

    private class OnPackItemCompletedHandler implements OnPackItemCompletedListener {
        @Override
        public void onPackItemCompleted(PackItem packItem) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    puzzleAdapter.markAsChanged();
                }
            });
        }
    }
}
